#include <vector>
#include <cstdint>
#include <cstddef>
#include <cassert>
#include <cmath>
#include <memory>
#include "DynamicThreadPool/include/log/include/log.h"

/*使用环形缓冲区*/

class Buffer
{
public:
    typedef std::vector<char>::iterator it;

    Buffer(size_t size = 1024)
    : _buffer(std::make_unique<std::vector<char>>(size))
    , _readIdx(0)
    , _writeIdx(0)
    , lg(1)
    {
    }

    char* getStartWrite()  /*写开始位置*/
    {
        return begin() + _writeIdx;
    }

    char* getStartRead()  /*读开始位置*/
    {
        return begin() + _readIdx;
    }

    uint64_t getHeadIdleSize()  /*前沿空闲空间大小*/
    {
        if (_readIdx < _writeIdx)
        {
            return _readIdx;
        }
        else
        {
            return _readIdx - _writeIdx;
        }
    }

    uint64_t getTailIdleSize()  /*后沿空闲空间大小*/
    {
        return size() - _writeIdx;
    }

    uint64_t getTotalIdleSize()  /*可写空间大小*/
    {
        return getHeadIdleSize() + getTailIdleSize();
    }

    uint64_t getUsedSpaceSize()
    {
        if (_readIdx <= _writeIdx)
        {
            return _writeIdx - _readIdx;
        }
        else
        {
            return _writeIdx + size() - _readIdx;
        }
    }

    void writeMove(uint64_t len)  /*写位置移动*/
    {
        if (len > getTotalIdleSize())
        {
            lg(Error, __LINE__, "Buffer writeMove len outweigh total idle space size");
            assert(len <= getTotalIdleSize());
        }

        _writeIdx = (_writeIdx + len) % size();
    }

    void readMove(uint64_t len)  /*读位置移动*/
    {
        if (len > getUsedSpaceSize())
        {
            lg(Error, __LINE__, "Buffer writeMove len outweigh total idle space size");
            assert(len <= getUsedSpaceSize());
        }

        _readIdx = (_readIdx + len) % size();
    }

    void checkWriteSpace(uint64_t len)  /*判断写入空间是否足够, 不足够就扩容*/
    {
        //写入空间足够
        if (len <= getTotalIdleSize())
        {
            return;
        }
        else
        {
            //写入空间不够，扩容
            expansion(len);
        }
    }

    void clear()  /*清理缓冲区*/
    {
        _readIdx = _writeIdx = 0;
    }

   

private:

    char* begin()
    {
        return &(*_buffer->begin());
    }

    char* end()
    {
        return &(*_buffer->end());
    }

    uint64_t size()
    {
        return static_cast<uint64_t>(_buffer->size());
    }

    void expansion(uint64_t len)
    {
        size_t newSize = size() + std::max(len, size()); /*翻倍扩容*/
        std::vector<char> newBuffer(newSize);
        
        // 复制现有数据
        if (_readIdx <= _writeIdx) 
        {
            std::copy(getStartRead(), getStartWrite(), newBuffer.begin());
        } 
        else 
        {
            size_t tailSize = end() - getStartRead();
            std::copy(getStartRead(), end(), newBuffer.begin());
            std::copy(begin(), getStartWrite(), newBuffer.begin() + tailSize);
        }
        
        // 更新索引
        _writeIdx = getUsedSpaceSize(); 
        _readIdx = 0;
        
        _buffer->swap(newBuffer);
    }


private:

    std::unique_ptr<std::vector<char>> _buffer;  

    uint64_t _readIdx;  /*读偏移*/

    uint64_t _writeIdx;  /*写偏移*/

    xxhhdzl::log lg;
};
